/*
 The surface-physics project: http://code.google.com/p/surface-physics/
 Adds real world physics based on the Bullet physics engine, to bases in the Orbiter space
 flight simulation software.

 Written by Abhijit Nandy
 License : Apache License 2.0

 Bump_VesselCollisionDefCache.h

 Used to maintain a cache of vessel definitions and return a structure filled with the
 passed vessel's definition.

 Decided not to make it a singleton as its a cache and we are not bothered with saving memory here
 However we ARE trying to have just one object of this cache class, but this is not absolutely
 necessary. Currently we have one cache sim-wide, but later on more cache objects with some specific
 vessel definitions in them may be required.

 This is the central point for all collision information thats shared among vessels.

 References:
 http://stackoverflow.com/questions/86582/singleton-how-should-it-be-used


*/


#pragma once

// STL
#include <string>
#include <unordered_map>

// Orbiter
#include "orbitersdk.h"
#include "VesselCollisionDef.h"

// Bullet
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btConeShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"


#define V3ARGS(a)    (a).x, (a).y, (a).z

typedef std::tr1::unordered_map<std::string, VesselCollisionDef*> CollisionDefCache;// Orbiter-Bump object map


/**
 * The Bump_VesselCollisionDefCache class to manage a vessel collision mesh definition cache
 *
 */
class Bump_VesselCollisionDefCache
{
	// Constants

	// We can restrict the number of vertices loaded here
	static const int MAX_VERTICES = 512;

	// Unordered map using hashes for keeping controlled VESSELs to skip against
	CollisionDefCache mCache;
	CollisionDefCache::iterator mCacheIter;

	// Physics file : used to read object configurations
	FILEHANDLE mPhysicsFile;

	// Read the chassis shapes section and create/add them to the compound shape in the
	// vessel def structure
	int 	readChassis(VesselCollisionDef* pVesselCollDef);

	// Read the properties section into a vessel definition
	int 	readProperties(VesselCollisionDef* pVesselCollDef);

	// Sets default values for all the mandatory properties - hard coded for now,
	// may read from a defaults file later
	int 	setDefaults(VesselCollisionDef* pVesselCollDef);

	// Load a MSH format mesh file as a convex hull
	int 	loadMsh(char *fileName, btConvexHullShape *convexHull);

	// Utility to set the transform using Euler angles
	void 	setTransform( btTransform& shpTransform,
					  	  float x, float y, float z,
					  	  float rx, float ry, float rz ) {

		btQuaternion q;
		shpTransform.setIdentity();
		shpTransform.setOrigin(btVector3(x, y, z));
		q.setEuler(ry*(btScalar)RAD, rx*(btScalar)RAD, rz*(btScalar)RAD);
		shpTransform.setRotation(q);
	}

	bool isValid(float x, float y, float z, float rx, float ry, float rz,
				   float p1, float p2, float p3);


public:

	Bump_VesselCollisionDefCache();
	~Bump_VesselCollisionDefCache();

	/**
	 * Return the definition if already in cache.
	 * Read and add vessel definition to cache if needed.
	 *
	 */
	VesselCollisionDef* getVesselCollisionDef(char *strVesselClassName);

	// Prints the whole cache
	void	printCache(void);

	// Prints a single vessel collision definition - used by printCache() & others
	void 	printVesselCollisionDef(VesselCollisionDef* pVesselCollDef);

};
